package com.catazy.base.presentation.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.catazy.base.BuildConfig
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlin.properties.Delegates

/**
 * 作者: Tao
 * 日期: 2024/12/16
 * 时间: 16:21
 * 描述: BaseViewModel
 */
abstract class BaseViewModel<State : BaseState, Action : BaseAction<State>>(initialState: State) :
    ViewModel() {
    // MutableStateFlow 是一种响应式流（reactive stream），用于在应用程序中管理状态的变化
    // MutableStateFlow 常用于在 ViewModel 中管理 UI 状态，因为它可以确保 UI 始终显示最新的状态，并且可以轻松地从任何地方更新状态
    private val _uiStateFlow = MutableStateFlow(initialState)
    // 将一个 MutableStateFlow 转换为不可变的 StateFlow。
    // 这样做的目的是为了隐藏 MutableStateFlow 的可变性，只暴露其只读视图，从而确保状态只能从特定的地方进行修改，而其他地方只能读取状态
    val uiStateFlow = _uiStateFlow.asStateFlow()

    private var stateTimeTravelDebugger: StateTimeTravelDebugger? = null

    init {
        if (BuildConfig.DEBUG){
            stateTimeTravelDebugger = StateTimeTravelDebugger(this::class.java.simpleName)
        }
    }

    /**
     * 状态-委托属性管擦
     *  Delegates.observable 来创建一个可观察的属性委托
     *  业务逻辑是：
     */
    private var state by Delegates.observable(initialState) { _,old,new->
        // 检查新旧状态是否不同
        if (old != new){
            // 使用 viewModelScope.launch 启动一个新的协程，并在该协程中更新 UI 状态
            viewModelScope.launch {
                _uiStateFlow.value = new
            }
            // 调用 StateTimeTravelDebugger 的方法来记录状态转换
            stateTimeTravelDebugger?.apply {
                addStateTransition(old,new)
                logLast()
            }
        }
    }

    /**
     * 发送一个动作，并根据动作更新状态
     */
    protected fun sendAction(action: Action){
        stateTimeTravelDebugger?.addAction(action)
        state = action.reduce(state)
    }
}